# Copyright 2008 Thomas Quemard
#
# Grabova is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published
# by the Free Software Foundation; either version 3.0, or (at your option)
# any later version.
#
# Grabova is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
# License for more details.

import ConfigParser
import grabova.client
import grabova.source
import re
import urlparse
import string

class ClientNotSuppored(Exception):
    pass

class Grabova:
    client = None
    shows = None

    def __init__(self):
        self.shows = Shows()

    def grab(self, show):
        items = show.source.get_items()
        max_seeders = 0
        torrent_url = ""
        torrent_title = ""
        torrent = []
        print "# <" + show.name + " @ S" + string.zfill(str(show.season),2) + "E" + string.zfill(str(show.episode), 2) + "> : Checking new episodes using <" + show.source.name + ">...",

        for item in items:
            ep = show.get_episode_number(item["title"])
            ep_season = ep[0]
            item["season"] = ep_season
            ep_num = ep[1]
            item["episode"] = ep_num

            size_down = int(show.size - show.size_aproximation)
            size_up = int(show.size + show.size_aproximation)

            if ep_season == show.season:
                if ep_num == show.episode + 1:
                    if item["size"] > size_down and item["size"] < size_up:
                        if item["seeders"] >= max_seeders:
                            torrent = item
                            max_seeders = item["seeders"]
                            torrent_url = item["url"]
                            torrent_title = item["title"]

                elif ep_num > show.episode:
                    print "\n# You seem to have missed episodes: S" + str(ep_season) + "E" + str(ep_num) + " is already out,",
                    print "and you are only at S" + str(show.season) + "E" + str(show.episode) + ".",
                    print "Please, catch up yourself :}"

        if torrent_url != "":
            print "YES <" + torrent_title + "> at <" + torrent_url + ">"
            self.client.run(torrent_title, torrent_url)
            show.episode = torrent["episode"]
        else:
            print "No"


    def grab_all(self):
        for show in self.shows:
            self.grab(show)

    def load(self, config_file):
        cfg = ConfigParser.ConfigParser()
        cfg.read(config_file)
        client_name = cfg.get("grabova", "client")
        client_name = client_name.lower()

        if client_name == "azureus":
            self.set_client(grabova.client.Azureus())
        elif client_name == "bittorrent":
            self.set_client(grabova.client.BitTorrent())
        elif client_name == "deluge":
            self.set_client(grabova.client.Deluge())
        elif client_name == "null":
            self.set_client(grabova.client.Null())
        elif client_name == "transmission":
            self.set_client(grabova.client.Transmission())
        else:
            raise ClientNotSupported()

    def set_client(self, client):
        self.client = client

class Show:
    blockers = []
    episode = 0
    name = ""
    season = 0
    size = 0
    size_aproximation = 0
    source = None

    def get_episode_number(self, s):
        e = re.compile("[sS]?(\d+)[eEx](\d+)")
        matches = None
        if e != None:
            matches = e.search(s)

        if matches != None:
            groups = matches.groups()
            if len(groups) == 2:
                return (int(groups[0]), int(groups[1]))
            else:
                return ("", "")
        else:
            return ("", "")


    def set_blockers(self, blockers):
        pass

    def set_size(self, size):
        self.size = self.translate_size_to_bytes(size)

    def set_size_aproximation(self, size):
        self.size_aproximation = self.translate_size_to_bytes(size)

    def translate_size_to_bytes(self, s):
        if len(s) > 0:
            unit = s[len(s) - 1]

            if unit.isalpha():
                size = int(s[0:-1])
                if unit == "k" or unit == "K":
                    size = size * 1024
                elif unit == "m" or unit =="M":
                    size = size * 1048576
            else:
                size = int(s)

            return int(size)

    def translate_byte_size_to_string_size(self, i):
        result = "0"
        if i > 1048576:
            result = str(i / 1048576) + "M"
        elif i > 1024:
            result = str(i / 1024) + "K"
        else:
            result = str(i)

        return result

    def set_source(self, str):
        url = urlparse.urlparse(str)
        self.source = None
        if url[0] == "mininova":
            self.source = source.Mininova()

        if self.source != None:
            self.source.import_source(str)


class Shows (list):

    def add_show(self, show):
        self.append(show)

    def export_to_config(self):
        cfg = ConfigParser.ConfigParser()
        for show in self:
            cfg.add_section(show.name)
            cfg.set(show.name, "season", show.season)
            cfg.set(show.name, "episode", show.episode)
            cfg.set(show.name, "source", show.source.export_source())
            cfg.set(show.name, "blockers", show.blockers)
            cfg.set(show.name, "size", show.translate_byte_size_to_string_size(show.size))
            cfg.set(show.name, "size_aproximation", show.translate_byte_size_to_string_size(show.size_aproximation))

        return cfg

    def load(self, config_path):
        ini = ConfigParser.ConfigParser()
        ini.read(config_path)
        for section in ini.sections():
            show = Show()
            show.name = section

            for item in ini.items(section):
                if item[0] == "source":
                    show.set_source(str(item[1]))
                elif item[0] == "blockers":
                    show.set_blockers(item[1])
                elif item[0] == "size":
                    show.set_size(item[1])
                elif item[0] == "size_aproximation":
                    show.set_size_aproximation(item[1])
                elif item[0] == "season":
                    show.season = int(item[1])
                elif item[0] == "episode":
                    show.episode = int(item[1])
            self.add_show(show)

    def save(self, config_path):
        cfg = self.export_to_config()
        file = open(config_path, "w")
        cfg.write(file)
        file.close()



